/**
 * 事件驱动装备组件示例
 * 展示如何使用事件总线替代直接的getComponent依赖
 */

import { DataEquip } from "../../shared/face";
import { EventDrivenComponent } from "../../infrastructure/events/EventDrivenComponent";
import { COMPONENT_EVENTS } from "../../infrastructure/events/ComponentEvents";
import { ComponentEvent } from "../../infrastructure/events/ComponentEventBus";
import { EquipService } from "../../service/EquipService";
import { analysisIntent } from "../../core/tool/baseScene";

/**
 * 事件驱动装备组件
 * 演示如何通过事件通信来解耦组件依赖
 */
export class EventDrivenEquipComponent extends EventDrivenComponent {
    private _equipService: EquipService;
    slot: DataEquip[] = [];

    constructor() {
        super();
        // 使用依赖注入获取EquipService
        this._equipService = this.getService<EquipService>('EquipService');
    }

    init() {
        this.logger.info('EventDrivenEquipComponent initialized');
    }

    /**
     * 设置事件监听器
     */
    protected setupEventListeners(): void {
        // 监听其他组件可能影响装备的事件
        this.onRPGEvents({
            onLevelUp: this.handlePlayerLevelUp.bind(this),
            onAttributeChanged: this.handleAttributeChanged.bind(this)
        });

        // 监听背包事件，可能需要响应装备操作
        this.onBagEvents({
            onItemAdded: this.handleItemAdded.bind(this),
            onItemRemoved: this.handleItemRemoved.bind(this)
        });

        this.logger.debug('Equipment component event listeners setup completed');
    }

    /**
     * 装备穿戴（原有逻辑，现在通过事件通知其他组件）
     */
    async addEquip(equip: DataEquip): Promise<void> {
        try {
            const result = this._equipService.equipItem(equip, this.slot);
            
            if (!result.success) {
                this.client_text(result.message);
                return;
            }

            // 更新装备栏
            this.slot = result.newEquipList;
            
            // 🎯 关键改进：通过事件通知，而不是直接调用其他组件
            
            // 1. 如果有被替换的装备，发射事件通知背包组件
            if (result.replacedEquip) {
                const item = this._equipService.equipToItem(result.replacedEquip);
                
                // 发射装备被替换事件
                await this.emitEquipmentReplaced(equip, result.replacedEquip);
                
                // 发射物品添加事件，背包组件会监听此事件
                await this.emitItemAdded(item, '装备替换');
            } else {
                // 发射装备穿戴事件
                await this.emitEquipmentEquipped(equip);
            }
            
            // 2. 发射装备属性变化事件，RPG组件会监听此事件来更新技能和战力
            await this.emitEvent(COMPONENT_EVENTS.EQUIPMENT.STATS_CHANGED, {
                playerId: this.id,
                equipment: equip,
                stats: result.statsChange || {}
            });

            this.client_text(result.message);
            
            this.logger.info('Equipment added successfully', {
                metadata: { equipId: equip.id, hasReplacement: !!result.replacedEquip }
            });

        } catch (error) {
            const gameError = this.errorHandler.handleError(error, 'addEquip');
            this.client_text('装备穿戴失败');
            this.logger.error('Failed to add equipment', gameError);
        }
    }

    /**
     * 装备卸载（原有逻辑，现在通过事件通知其他组件）
     */
    async removeEquip(slot: number): Promise<void> {
        try {
            const result = this._equipService.unequipItem(slot, this.slot);
            
            if (!result.success) {
                this.client_text(result.message);
                return;
            }

            // 更新装备栏
            this.slot = result.newEquipList;
            
            // 🎯 关键改进：通过事件通知，而不是直接调用其他组件
            
            // 1. 发射装备卸载事件
            if (result.unequippedEquip) {
                await this.emitEquipmentUnequipped(result.unequippedEquip, slot);
                
                // 2. 发射物品添加事件，背包组件会监听此事件
                const item = this._equipService.equipToItem(result.unequippedEquip);
                await this.emitItemAdded(item, '装备卸载');
            }
            
            // 3. 发射装备属性变化事件
            await this.emitEvent(COMPONENT_EVENTS.EQUIPMENT.STATS_CHANGED, {
                playerId: this.id,
                equipment: null,
                stats: result.statsChange || {}
            });

            this.client_text(result.message);
            
            this.logger.info('Equipment removed successfully', {
                metadata: { slot }
            });

        } catch (error) {
            const gameError = this.errorHandler.handleError(error, 'removeEquip');
            this.client_text('装备卸载失败');
            this.logger.error('Failed to remove equipment', gameError);
        }
    }

    /**
     * 清空所有装备
     */
    async clearAllEquips(): Promise<void> {
        try {
            const removedEquips: DataEquip[] = [];
            
            // 收集所有装备
            for (let i = 0; i < this.slot.length; i++) {
                if (this.slot[i]) {
                    removedEquips.push(this.slot[i]);
                }
            }
            
            // 清空装备栏
            this.slot = [];
            
            // 🎯 关键改进：通过事件批量通知
            for (const equip of removedEquips) {
                await this.emitEquipmentUnequipped(equip);
                
                const item = this._equipService.equipToItem(equip);
                await this.emitItemAdded(item, '装备清空');
            }
            
            // 发射装备属性变化事件
            await this.emitEvent(COMPONENT_EVENTS.EQUIPMENT.STATS_CHANGED, {
                playerId: this.id,
                equipment: null,
                stats: { allCleared: true }
            });

            this.client_text('所有装备已卸载');
            this.logger.info('All equipment cleared');

        } catch (error) {
            const gameError = this.errorHandler.handleError(error, 'clearAllEquips');
            this.client_text('装备清空失败');
            this.logger.error('Failed to clear all equipment', gameError);
        }
    }

    // ==================== 事件处理器 ====================

    /**
     * 处理玩家升级事件
     */
    private async handlePlayerLevelUp(data: any, event: ComponentEvent): Promise<void> {
        // 当玩家升级时，可能解锁新的装备槽位或装备需求
        this.logger.debug('Player level up detected, checking equipment requirements', {
            metadata: { oldLevel: data.oldLevel, newLevel: data.newLevel }
        });

        // 检查是否有装备因为等级提升而变化
        // 这里可以添加装备需求验证逻辑
    }

    /**
     * 处理属性变化事件
     */
    private async handleAttributeChanged(data: any, event: ComponentEvent): Promise<void> {
        // 当属性变化时，可能需要重新计算装备效果
        if (data.attribute && this.shouldRecalculateEquipmentStats(data.attribute.name)) {
            this.logger.debug('Attribute changed, may need to recalculate equipment stats', {
                metadata: { attribute: data.attribute.name, oldValue: data.attribute.oldValue, newValue: data.attribute.newValue }
            });
            
            // 发射装备属性重新计算事件
            await this.emitEvent(COMPONENT_EVENTS.EQUIPMENT.STATS_CHANGED, {
                playerId: this.id,
                equipment: null,
                stats: { recalculated: true, trigger: data.attribute.name }
            });
        }
    }

    /**
     * 处理物品添加事件
     */
    private async handleItemAdded(data: any, event: ComponentEvent): Promise<void> {
        // 当背包添加物品时，如果是装备类物品，可能需要检查自动装备
        if (data.item && data.item.type === 'equipment' && data.reason === '获得装备') {
            this.logger.debug('Equipment item added to bag, checking auto-equip', {
                metadata: { itemId: data.item.id, reason: data.reason }
            });
            
            // 这里可以添加自动装备逻辑
            // 例如：如果当前槽位为空，自动装备更好的装备
        }
    }

    /**
     * 处理物品移除事件
     */
    private async handleItemRemoved(data: any, event: ComponentEvent): Promise<void> {
        // 当背包移除物品时，可能需要记录或处理
        if (data.item && data.item.type === 'equipment') {
            this.logger.debug('Equipment item removed from bag', {
                metadata: { itemId: data.item.id, reason: data.reason }
            });
        }
    }

    // ==================== 辅助方法 ====================

    /**
     * 判断是否应该重新计算装备属性
     */
    private shouldRecalculateEquipmentStats(attributeName: string): boolean {
        // 定义哪些属性变化需要重新计算装备效果
        const relevantAttributes = ['strength', 'agility', 'intelligence', 'level'];
        return relevantAttributes.includes(attributeName.toLowerCase());
    }

    /**
     * 获取装备总属性（用于其他组件查询）
     */
    getEquipmentStats(): any {
        return this._equipService.calculateTotalStats(this.slot);
    }

    /**
     * 检查是否可以装备某个物品
     */
    canEquip(equipment: DataEquip): boolean {
        return this._equipService.canEquipItem(equipment, this.slot);
    }

    // ==================== 客户端交互方法 ====================

    /**
     * 客户端装备穿戴命令
     */
    async client_equip(data: analysisIntent): Promise<void> {
        // 解析装备参数并调用addEquip
        // 这里保持原有的客户端交互逻辑不变
        this.logger.debug('Client equip command received', {
            metadata: { command: data.intent }
        });
        
        // 实现具体的装备逻辑...
    }

    /**
     * 客户端装备卸载命令
     */
    async client_unequip(data: analysisIntent): Promise<void> {
        // 解析卸载参数并调用removeEquip
        this.logger.debug('Client unequip command received', {
            metadata: { command: data.intent }
        });
        
        // 实现具体的卸载逻辑...
    }
}

/**
 * 导出便于使用的装备组件类型
 */
export default EventDrivenEquipComponent;
